package com.zb.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zb.entity.*;
import com.zb.mapper.ZjStorePositionMapper;
import com.zb.result.PageUtil;
import com.zb.service.*;
import com.zb.vo.StorePositionListVo;
import com.zb.vo.StorePositionVo;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 仓库仓位表 服务实现类
 * </p>
 *
 * @author WEN
 * @since 2024-01-06
 */
@Service
public class ZjStorePositionServiceImpl extends ServiceImpl<ZjStorePositionMapper, ZjStorePosition> implements ZjStorePositionService {
    @Resource
    private ZjStoreGoodsStockService storeGoodsStockService;
    @Resource
    private ZjStoreGoodsStockCodeService storeGoodsStockCodeService;
    @Resource
    private ZjStoreInboundMaterialService storeInboundMaterialService;
    @Resource
    private ZjStoreOutboundMaterialService storeOutboundMaterialService;
    // 保存仓库仓位
    @Override
    public void save(Long custAccId, Long storeId, List<StorePositionVo> storePositionVos) {
        if (CollectionUtil.isEmpty(storePositionVos)) {
            return;
        }
        Assert.isTrue(storePositionVos.size() == storePositionVos.stream().map(StorePositionVo::getName).distinct().toList().size(), "仓位名称已重复！");
        disabledByIds(storePositionVos.stream().filter(f -> null != f.getId() && f.getStatus()).map(StorePositionVo::getId).toList(), false);

        List<ZjStorePosition> adds = new ArrayList<>();
        List<ZjStorePosition> updates = new ArrayList<>();
        ZjStorePosition position = null;
        for (StorePositionVo vo : storePositionVos) {
            position = new ZjStorePosition();
            BeanUtil.copyProperties(vo, position);
            position.setDisabled(vo.getStatus());
            if (null != position.getId()) {
                updates.add(position);
                continue;
            }
            position.setId(IdWorker.getId());
            position.setCustAccId(custAccId);
            position.setStoreId(storeId);
            adds.add(position);
        }
        if (CollectionUtil.isNotEmpty(adds)) this.saveBatch(adds);
        if (CollectionUtil.isNotEmpty(updates)) this.updateBatchById(updates);
    }

    // 根据仓库仓位ID禁用仓位
    @Override
    public void disabledByIds(List<Long> ids, boolean excuteUpdate) {
        if (CollectionUtil.isEmpty(ids)) {
            return;
        }

        QueryWrapper<ZjStoreGoodsStock> goodsStockQueryWrapper = new QueryWrapper<>();
        goodsStockQueryWrapper.select("store_position_id");
        goodsStockQueryWrapper.in("store_position_id", ids).eq("system_stock", 0);
        List<ZjStoreGoodsStock> goodsStockList = storeGoodsStockService.list(goodsStockQueryWrapper);
        if (CollectionUtil.isNotEmpty(goodsStockList)) {
            ids.removeIf(f2 -> goodsStockList.stream().anyMatch(f -> Objects.equals(f.getStorePositionId(), f2)));
            if (CollectionUtil.isNotEmpty(ids)) {
                QueryWrapper<ZjStorePosition> wrapper = new QueryWrapper<>();
                wrapper.select("id", "name");
                wrapper.in("id", ids);
                List<ZjStorePosition> positionList = this.list(wrapper);
                Assert.isTrue(false, "仓位[ "+ positionList.stream().map(ZjStorePosition::getName).collect(Collectors.joining("、"))+" ]已有库存，不允许禁用");
            }
        }
        if (excuteUpdate) {
            List<ZjStorePosition> updates = new ArrayList<>();
            ZjStorePosition position = null;
            for (Long id : ids) {
                position = new ZjStorePosition();
                position.setId(id);
                position.setDisabled(true);
                updates.add(position);
            }
            this.updateBatchById(updates);
        }
    }

    // 根据仓库仓位ID删除
    @Override
    public void deleteByIds(List<Long> ids) {
        if (CollectionUtil.isEmpty(ids)) {
            return;
        }
        List<Long> positionIds =  storeGoodsStockCodeService.getStorePositioinIdByDelStorePositionIds(ids);
        exceptionMessage(positionIds, "商品库存");
        positionIds = storeInboundMaterialService.getStorePositionIdsByDelStorePositionIds(ids);
        exceptionMessage(positionIds, "入库商品仓位");
        positionIds = storeOutboundMaterialService.getStorePositionIdsByDelStorePositionIds(ids);
        exceptionMessage(positionIds, "出库商品仓位");
        this.removeByIds(ids);
    }

    private void exceptionMessage(List<Long> ids, String message) {
        if (CollectionUtil.isEmpty(ids)) {
            return;
        }
        QueryWrapper<ZjStorePosition> wrapper = new QueryWrapper<>();
        wrapper.select("name");
        wrapper.in("id", ids);
        List<ZjStorePosition> positionList = this.list(wrapper);
        Assert.isTrue(false, "仓位[ " + positionList.stream().map(ZjStorePosition::getName).collect(Collectors.joining("、")) + " ]与" + message + "关联，不允许删除");
    }

    // 根据仓库ID获取仓位下拉列表
    @Override
    public Map<String, Object> storePositionPageSelect(Long storeId, SelectVo selectVo) {
        PageUtil.setSelectPageLimit(selectVo);
        QueryWrapper<ZjStorePosition> wrapper = new QueryWrapper<>();
        wrapper.select("id", "name");
        wrapper.eq("store_id", storeId).eq("is_disabled", false);
        if (StringUtils.isNotBlank(selectVo.getName())) {
            wrapper.like("name", selectVo.getName());
        }
        Page<ZjStorePosition> page = this.page(new Page<>(selectVo.getPage(), selectVo.getLimit()), wrapper);
        return PageUtil.pageList(page.getCurrent(), page.getSize(), page.getTotal(), page.getRecords().stream().map(po -> {
            return new SelectResultVo(po.getId(), po.getName());
        }).toList());
    }

    // 根据仓位ID获取仓位名称
    @Override
    public List<ZjStorePosition> getStorePositionNameByIds(List<Long> ids) {
        if (CollectionUtil.isEmpty(ids)) {
            return new ArrayList<>();
        }
        QueryWrapper<ZjStorePosition> wrapper = new QueryWrapper<>();
        wrapper.select("id", "name", "store_id");
        wrapper.in("id", ids);
        return this.list(wrapper);
    }

    // 根据仓库ID获取仓位数据
    @Override
    public List<ZjStorePosition> getByStoreId(Long storeId) {
        QueryWrapper<ZjStorePosition> wrapper = new QueryWrapper<>();
        wrapper.select("id", "name", "store_id", "is_disabled AS disabled");
        wrapper.eq("store_id", storeId);
        return this.list(wrapper);
    }

    // 根据仓库ID获取仓位列表
    @Override
    public Map<String, Object> getStorePositionList(Long storeId, SelectVo selectVo) {
        PageUtil.setPageLimit(selectVo);
        QueryWrapper<ZjStorePosition> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("gmt_update");
        wrapper.eq("store_id", storeId);
        if (StringUtils.isNotBlank(selectVo.getName())){
            wrapper.like("name", selectVo.getName());
        }
        Page<ZjStorePosition> page = this.page(new Page<>(selectVo.getPage(), selectVo.getLimit()), wrapper);
        List<Long> storePositionIds = page.getRecords().stream().map(ZjStorePosition::getId).toList();
        List<ZjStoreGoodsStock> storeGoodsStockList = storeGoodsStockService.getSystemStockGroupByStorePositionIds(storePositionIds);
        List<ZjStoreInboundMaterial> inboundMaterials = storeInboundMaterialService.getInStoreQtyGroupByStorePositionIds(storePositionIds);
        List<ZjStoreOutboundMaterial> outboundMaterials = storeOutboundMaterialService.getOutStoreQtyGroupByStorePositionIds(storePositionIds);
        List<StorePositionListVo> voList = page.getRecords().stream().map(po -> {
            StorePositionListVo vo = new StorePositionListVo();
            BeanUtil.copyProperties(po, vo);
            vo.setStatus(po.getDisabled());
            vo.setCreateTime(po.getGmtCreate());
            vo.setUpdateTime(po.getGmtUpdate());
            vo.setSystemStock(storeGoodsStockList.stream().filter(f -> Objects.equals(f.getStorePositionId(), po.getId())).map(ZjStoreGoodsStock::getSystemStock).findFirst().orElse(0L));
            vo.setAvailableStock(new BigDecimal(vo.getSystemStock()+"")
                    .add(new BigDecimal(inboundMaterials.stream().filter(f -> Objects.equals(f.getStorePositionId(), po.getId())).map(ZjStoreInboundMaterial::getQty).findFirst().orElse(0L).toString()))
                    .subtract(new BigDecimal(outboundMaterials.stream().filter(f -> Objects.equals(f.getStorePositionId(), po.getId())).map(ZjStoreOutboundMaterial::getQty).findFirst().orElse(0L).toString()))
                    .longValue()
            );
            return vo;
        }).toList();
        return PageUtil.pageList(page.getCurrent(), page.getSize(), page.getTotal(), voList);
    }
}
